import { Controller, Get, Query, Param, HttpException, HttpStatus } from '@nestjs/common';
import axios from '../shared/axios.instance';
import { SourceService } from '../source/source.service';
import { SourceParserService } from '../source/source-parser.service';

/**
 * 辅助函数：根据 searchUrl 模板和关键词构造请求参数
 */
function buildSearchRequest(searchUrlTemplate: string, keyword: string, page: number, baseUrl: string): { url: string, method: string, headers: any, body?: string } {
  // 如果模板中包含 "{{" 且包含逗号，则当作动态模板进行处理
  if (searchUrlTemplate.includes("{{") && searchUrlTemplate.includes("}}") && searchUrlTemplate.includes(",")) {
    // 例如模板如下： 
    // "{{url=source.getKey();cookie.removeCookie(url)}}/search/,{
    //   "charset": "UTF-8",
    //   "method": "POST",
    //   "body": "searchkey={{key}}&Submit=搜索"
    // }"
    //
    // 第一部分：从模板中去除 {{...}} 部分（如果有的话），取逗号之前的部分作为 URL 模板
    let urlPart = searchUrlTemplate.split(",")[0].trim();
    // 去除里面的动态脚本标记（例如将 "{{url=source.getKey();cookie.removeCookie(url)}}" 移除）
    urlPart = urlPart.replace(/{{.*?}}/g, "");
    // 替换 URL 中的 {{key}} 占位符
    urlPart = urlPart.replace("{{key}}", encodeURIComponent(keyword));
    // 同时替换页码占位符（如果有）
    urlPart = urlPart.replace("{{page}}", page.toString());
    // 第二部分：逗号后面的部分当作 JSON 配置
    let jsonPart = searchUrlTemplate.substring(searchUrlTemplate.indexOf(",") + 1).trim();
    let config: any = {};
    try {
      config = JSON.parse(jsonPart);
    } catch (e) {
      config = {}; // 如果解析失败，则默认空配置
    }
    return {
      url: urlPart,
      method: config.method || "GET",
      body: config.body ? config.body.replace("{{key}}", encodeURIComponent(keyword)) : undefined,
      headers: { 'User-Agent': 'Mozilla/5.0', ...(config.header || {}) }
    };
  } else {
    // 简单模板：直接替换占位符
    let url = searchUrlTemplate.replace("{{key}}", encodeURIComponent(keyword));
    url = url.replace("{{page}}", page.toString());
    // 如果 url 不是绝对路径，则与 baseUrl 拼接
    if (!/^https?:\/\//.test(url)) {
      if (baseUrl.endsWith("/") && url.startsWith("/")) {
        url = baseUrl + url.substring(1);
      } else if (!baseUrl.endsWith("/") && !url.startsWith("/")) {
        url = baseUrl + "/" + url;
      } else {
        url = baseUrl + url;
      }
    }
    return {
      url,
      method: "GET",
      headers: { 'User-Agent': 'Mozilla/5.0' }
    };
  }
}

@Controller('search')
export class SearchController {
  constructor(
    private readonly sourceService: SourceService,
    private readonly sourceParserService: SourceParserService,
  ) { }

  /**
   * 通过书源和关键词搜索小说  
   * 示例接口： GET /search/novel/:sourceId?keyword=xxx&page=1
   */
  @Get('/novel/:sourceId')
  async searchNovels(
    @Param('sourceId') sourceId: string,
    @Query('keyword') keyword: string,
    @Query('page') page: number = 1,
  ): Promise<any> {
    const source = await this.sourceService.findOne(+sourceId);
    if (!source) {
      throw new HttpException('书源不存在', HttpStatus.NOT_FOUND);
    }
    if (!source.rules || !source.rules.searchUrl) {
      throw new HttpException('书源未配置搜索 URL', HttpStatus.BAD_REQUEST);
    }
    const requestParams = buildSearchRequest(source.rules.searchUrl, keyword, page, source.rules.bookSourceUrl);
    try {
      let response;
      if (requestParams.method.toUpperCase() === "POST") {
        response = await axios.post(requestParams.url, requestParams.body, { headers: requestParams.headers });
      } else {
        response = await axios.get(requestParams.url, { headers: requestParams.headers });
      }
      const html = response.data;
      if (!source.rules.ruleSearch) {
        throw new HttpException('书源未配置搜索解析规则', HttpStatus.BAD_REQUEST);
      }
      // 调用解析搜索结果的方法
      const results = this.sourceParserService.parseSearchResults(html, source.rules.ruleSearch);
      return results;
    } catch (error) {
      throw new HttpException(`搜索小说失败: ${error.message}`, HttpStatus.BAD_GATEWAY);
    }
  }
}